﻿using System;
using Honeycomb.Core;
using Honeycomb.Protocol.Messages;
using Honeycomb.Transport;

namespace Honeycomb.Protocol
{
    /// <summary>
    /// Protocol client is responsible for the protocol implementation on the client.
    /// </summary>
    public sealed class ProtocolClient : ProtocolBase
    {
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="networkClient">INetworkClient implementation.</param>
        public ProtocolClient(INetworkClient networkClient) : base(networkClient)
        {
        }

        /// <summary>
        /// Send authentication request.
        /// </summary>
        /// <param name="username">Username.</param>
        /// <param name="password">Password.</param>
        public void SendAuthenticateRequest(string username, string password)
        {
            Send(new AuthenticateRequest { Username = username, Password = password });
        }

        /// <summary>
        /// Read authentication response.
        /// </summary>
        /// <returns>True if authenticated, False if not.</returns>
        public bool ReadAuthenticateResponse()
        {
            return Read<AuthenticateResponse>().Authenticated;
        }

        /// <summary>
        /// Send task request.
        /// </summary>
        public void SendTaskRequest()
        {
            Send(new TaskRequest());
        }

        /// <summary>
        /// Read task response.
        /// </summary>
        /// <returns>Serialized task.</returns>
        public byte[] ReadTaskResponse()
        {
            return Read<TaskResponse>().SerializedTask;
        }

        /// <summary>
        /// Send assembly request.
        /// </summary>
        /// <param name="assemblyName">Full name of the assembly.</param>
        public void SendAssemblyRequest(string assemblyName)
        {
            Send(new AssemblyRequest { AssemblyName = assemblyName });
        }

        /// <summary>
        /// Read assembly response.
        /// </summary>
        /// <returns>Serialized assembly.</returns>
        public byte[] ReadAssemblyResponse()
        {
            return Read<AssemblyResponse>().Assembly;
        }

        /// <summary>
        /// Send result request.
        /// </summary>
        /// <param name="task">Task to send result for.</param>
        /// <param name="result">Result.</param>
        /// <param name="exception">Exception.</param>
        public void SendResultRequest(TaskBase task, object result, Exception exception)
        {
            Send(new ResultRequest { Task = task, Exception = exception, Result = result });
        }

        /// <summary>
        /// Read result response.
        /// </summary>
        public void ReadResultResponse()
        {
            Read<ResultResponse>();
        }
    }
}